package com.ecosoft.config;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ecosoft.config.helpers.ClasspathResourceScanner;
import com.ecosoft.config.spi.IConfigContext;
import com.ecosoft.config.spi.IConfigProvider;

final class ProviderNotifier {
	private static final Logger LOG = LoggerFactory.getLogger(ProviderNotifier.class);
	private IConfigContext configContext;
	public ProviderNotifier(String configDir)
	{
		this.configContext = new ConfigContext(configDir);
		this.initContextAttributes();
	}
	public void notifyProvider()
	{
		try {
			List<Class> providers = ClasspathResourceScanner.findConfiguredImplementations(IConfigProvider.class);
			 for (Class p : providers) {
	                try {
	                    ((IConfigProvider)p.newInstance()).notify(configContext);
	                } catch (Exception e) {
	                    LOG.warn("Unable to instantiate IConfigProvider for class " + p.getName());
	                }
	            }
		} catch (IOException e) {
			LOG.error("An error occurs during classpath scanning", e);
		}
	}
    private void initContextAttributes()
    {
    	Map<String,String> moduleConfig = initConfigModule();
    	String contextFileName = moduleConfig.get(Constants.CONTEXT_ATTRIBUTES_FILE_KEY);
    	File contextFile = this.configContext.getFileInCommonDir(contextFileName);
    	if(contextFile!=null&&contextFile.exists())
    	{
    		try {
    			FileInputStream fileInputStream = new FileInputStream(contextFile);
				Properties propertes = new Properties();
				propertes.load(fileInputStream);
				Map<String,String> contextAttributes = new HashMap<String,String>();
				this.fillMap(contextAttributes, propertes);
				((ConfigContext)configContext).setContextAttributes(contextAttributes);
			} catch (FileNotFoundException e) {
				LOG.error("The file ("+contextFile.getAbsolutePath()+") is not instanced to FileInputStream.",e);
			} catch (IOException e) {
				LOG.error("An error occurs during loading the context attributes file "+contextFile.getAbsolutePath()+".",e);
			}
    	}else
    	{
    		LOG.info("The context attributes file ("+contextFileName+") is not found ");
    	}
    }
	private  Map<String,String>  initConfigModule()
	{
		Map<String,String> configs = new HashMap<String,String>();
		URL defaultConfig = ProviderNotifier.class.getResource(Constants.DEFAULT_MODULE_CONFIG_FILENAME);
		Properties defaultPros = new Properties();
		try {
			defaultPros.load(defaultConfig.openStream());
			String fileName = defaultPros.getProperty(Constants.CONFIG_EXPAND_FILE_KEY);
			File expandedFile = configContext.getFileInCommonDir(fileName);
			if(expandedFile!=null)
			{
				if(LOG.isDebugEnabled())
				{
					LOG.debug("Pyramid module use the expanded config file :"+expandedFile.getAbsolutePath());
				}
				defaultPros.load(new FileInputStream(expandedFile));
			}
			fillMap(configs, defaultPros);
		} catch (Throwable e) {
			LOG.error("An error occurs during loading the default module file pyramid.properties.",e);
		}
		return configs;

	}
	private void fillMap(Map<String, String> configs, Properties defaultPros) {
		Enumeration iter = defaultPros.propertyNames();
		while (iter.hasMoreElements()) {
			String key = (String)iter.nextElement();
			String value = defaultPros.getProperty(key);
			configs.put(key, value);
		}
	}

}
